package com.cloud.rpc.filter;

import com.alibaba.fastjson.JSON;
import com.cloud.common.domain.CloudApplicationContext;
import com.cloud.common.domain.CloudContext;
import com.cloud.rpc.constants.RpcConStants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.rpc.*;

import java.util.Objects;

import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;

/**
 * rpc穿透 -> 供应者拦截器
 *
 * @author wangjian
 * @version 0.1.0
 * @create 2021年03月18日上午9:59
 * @since JDK 1.8
 * Life is so short,do something to make yourself happy,such as coding
 */
@Activate(group = CONSUMER, order = -200)
public class RpcConsumerFilter implements Filter, Filter.Listener {

    private static final Logger logger = LoggerFactory.getLogger(RpcProviderFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        RpcContext context = RpcContext.getContext();
        // 本端是否为消费端
        boolean consumerSide = context.isConsumerSide();
        if (consumerSide) {
            logger.info("As consumer, remoteHost :{" + context.getRemoteHost() + "}, methodName:{" + context.getMethodName() + "}");
            consumerSide(context);
        }
        //实际的rpc调用
        return invoker.invoke(invocation);
    }

    /**
     * 消费者从本地上下文设置RPC上下文
     */
    private void consumerSide(RpcContext context) {

        CloudContext cloudContext = CloudApplicationContext.getInstance().getContext();
        if (Objects.isNull(cloudContext.getAccId())) {
            logger.error("As consumer，CloudContext There was no transmission !!! remoteHost :{"
                    + context.getRemoteHost() + "}, methodName:{" + context.getMethodName() + "}");
            return;
        }
        context.setAttachment(RpcConStants.CLOUD_CONTEXT_MARK, JSON.toJSONString(cloudContext));
    }

    @Override
    public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {

    }

    @Override
    public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
        logger.error("RpcConsumerFilter传递时出现异常！", t);
        CloudApplicationContext.getInstance().removeContext();
    }
}
